/**
 * Copyrigth 2007 Aurelien Moreau
 * 
 * This file is part of ProcessShop.
 * 
 * ProcessShop is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 * 
 * ProcessShop is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with ProcessShop; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * $Id$
 */
package net.yienyien.process.pmm4bpmn.impl;

import java.util.Collection;
import java.util.HashSet;
import java.util.Set;

import net.yienyien.process.bpd.BPDModel;
import net.yienyien.process.bpd.BPDObject;
import net.yienyien.process.bpd.BpdPackage;
import net.yienyien.process.bpd.Event;
import net.yienyien.process.bpd.Task;

import net.yienyien.process.pmm.PmmFactory;
import net.yienyien.process.pmm4bpmn.Binding;
import net.yienyien.process.pmm4bpmn.Bindings;
import net.yienyien.process.pmm4bpmn.Pmm4bpmnPackage;

import org.eclipse.emf.common.notify.NotificationChain;

import org.eclipse.emf.common.util.EList;

import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.InternalEObject;

import org.eclipse.emf.ecore.impl.EObjectImpl;

import org.eclipse.emf.ecore.util.EObjectContainmentEList;
import org.eclipse.emf.ecore.util.InternalEList;
import org.eclipse.stp.bpmn.Activity;
import org.eclipse.stp.bpmn.MessagingEdge;
import org.eclipse.wst.wsdl.Operation;

/**
 * <!-- begin-user-doc -->
 * An implementation of the model object '<em><b>Bindings</b></em>'.
 * <!-- end-user-doc -->
 * <p>
 * The following features are implemented:
 * <ul>
 *   <li>{@link net.yienyien.process.pmm4bpmn.impl.BindingsImpl#getBindings <em>Bindings</em>}</li>
 * </ul>
 * </p>
 *
 * @generated
 */
public class BindingsImpl extends EObjectImpl implements Bindings {
	/**
	 * The cached value of the '{@link #getBindings() <em>Bindings</em>}' containment reference list.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @see #getBindings()
	 * @generated
	 * @ordered
	 */
	protected EList<Binding> bindings;

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	protected BindingsImpl() {
		super();
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	@Override
	protected EClass eStaticClass() {
		return Pmm4bpmnPackage.Literals.BINDINGS;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public EList<Binding> getBindings() {
		if (bindings == null) {
			bindings = new EObjectContainmentEList<Binding>(Binding.class, this, Pmm4bpmnPackage.BINDINGS__BINDINGS);
		}
		return bindings;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated NOT
	 */
	public net.yienyien.process.pmm.Bindings toPmm(BPDModel bpdModel) {
		net.yienyien.process.pmm.Bindings npb=PmmFactory.eINSTANCE.createBindings();
		for(Binding b: getBindings()) {
			
			if(b.getPool()!=null && b.getPool().equals(bpdModel.getFrom())) {
				s_toPmm(bpdModel, b, npb);
			} else if(isExternStyle(b.getActivity())) {
				e_toPmm(bpdModel, b, npb);
			} else {
				i_toPmm(bpdModel, b, npb);
			}
		}

		return npb;
	}
	
	private static void s_toPmm(BPDModel bpdModel, Binding b, net.yienyien.process.pmm.Bindings npb) {
		net.yienyien.process.pmm.ProcessBinding receive=PmmFactory.eINSTANCE.createProcessBinding();
		net.yienyien.process.pmm.ProcessBinding reply=PmmFactory.eINSTANCE.createProcessBinding();
		
		Operation op=b.getOperation();
		receive.setOperation(op);
		reply.setOperation(op);
				
		for(BPDObject o: bpdModel.getObjects()) {
			if(BpdPackage.eINSTANCE.getStartEvent().isInstance(o)) {
				receive.setEvent((Event) o);
			} else if(BpdPackage.eINSTANCE.getEndEvent().isInstance(o)) {
				reply.setEvent((Event)o);
			}
		}

		npb.getBindings().add(receive);
		npb.getBindings().add(reply);
	}
	
	private static void i_toPmm(BPDModel bpdModel, Binding b, net.yienyien.process.pmm.Bindings npb) {
			
			BPDObject t=back(bpdModel, b.getActivity());
			Operation op=b.getOperation();
			
			net.yienyien.process.pmm.Binding nb=null;
			if(BpdPackage.eINSTANCE.getTask().isInstance(t)) {
				net.yienyien.process.pmm.PartnerBinding tmp=PmmFactory.eINSTANCE.createPartnerBinding();
				tmp.setTask((Task) t);
				nb=tmp;
			} else if(BpdPackage.eINSTANCE.getIntermediateEvent().isInstance(t)){
				net.yienyien.process.pmm.ProcessBinding tmp=PmmFactory.eINSTANCE.createProcessBinding();
				tmp.setEvent((Event) t);
				nb=tmp;
			}

			nb.setOperation(op);
			nb.setRole(op.getName()+"Provider");
			npb.getBindings().add(nb);
	}
	
	private static void e_toPmm(BPDModel bpdModel, Binding b, net.yienyien.process.pmm.Bindings npb) {
			throw new UnsupportedOperationException();
			/*
			Operation op=b.getOperation();
			HashSet<Activity> rel=new HashSet<Activity>();
			for(MessagingEdge m: b.getActivity().getOutgoingMessages()) {
				rel.add(m.getTarget());
			}
			for(MessagingEdge m: b.getActivity().getIncomingMessages()) {
				rel.add(m.getSource());
			}
			Set<Task> ts=resolve(bpdModel, rel);
			
			for(Task t: ts) {
				net.yienyien.process.pmm.Binding nb=PmmFactory.eINSTANCE.createBinding();
				
				//nb.setTask(t);
				nb.setOperation(op);
				nb.setRole(b.getActivity().getGraph().getName());
				
				npb.getBindings().add(nb);
			}
			*/
	}
	
	private static BPDObject back(BPDModel bpdModel, Activity activity) {
		for(BPDObject o:bpdModel.getObjects()) {
			if(activity.equals(o.getFrom())) {
				return o;
			} 
		}
		return null;
	}
	
	private static boolean isExternStyle(Activity activity) {
		return activity.getOutgoingMessages().size()>0 || activity.getIncomingMessages().size()>0;
	}
	
	private static Set<Task> resolve(BPDModel bpdModel, Set<Activity> activities) {
		HashSet<Task> tasks=new HashSet<Task>();
		for(BPDObject o: bpdModel.getObjects()) {
			if(activities.contains(o.getFrom())) {
				tasks.add((Task) o);
			}
		}
		return tasks;
	}
	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	@Override
	public NotificationChain eInverseRemove(InternalEObject otherEnd, int featureID, NotificationChain msgs) {
		switch (featureID) {
			case Pmm4bpmnPackage.BINDINGS__BINDINGS:
				return ((InternalEList<?>)getBindings()).basicRemove(otherEnd, msgs);
		}
		return super.eInverseRemove(otherEnd, featureID, msgs);
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	@Override
	public Object eGet(int featureID, boolean resolve, boolean coreType) {
		switch (featureID) {
			case Pmm4bpmnPackage.BINDINGS__BINDINGS:
				return getBindings();
		}
		return super.eGet(featureID, resolve, coreType);
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	@SuppressWarnings("unchecked")
	@Override
	public void eSet(int featureID, Object newValue) {
		switch (featureID) {
			case Pmm4bpmnPackage.BINDINGS__BINDINGS:
				getBindings().clear();
				getBindings().addAll((Collection<? extends Binding>)newValue);
				return;
		}
		super.eSet(featureID, newValue);
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	@Override
	public void eUnset(int featureID) {
		switch (featureID) {
			case Pmm4bpmnPackage.BINDINGS__BINDINGS:
				getBindings().clear();
				return;
		}
		super.eUnset(featureID);
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	@Override
	public boolean eIsSet(int featureID) {
		switch (featureID) {
			case Pmm4bpmnPackage.BINDINGS__BINDINGS:
				return bindings != null && !bindings.isEmpty();
		}
		return super.eIsSet(featureID);
	}

} //BindingsImpl
